<html>
<head>
<style type="text/css">
  .main {
    background-color:#000;
	color:#fff;
  }
  ul {
    /*list-style: none;*/
    padding-left: 15px;
    font-size: 14px;
  }
  p {
    font-size: 12px;
  }
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</script>
<script>
$(document).ready(function(){
  String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.replace(new RegExp(search, 'g'), replacement);
  };
  String.prototype.replaceAt=function(index, replacement) {
    return this.substr(0, index) + replacement + this.substr(index + replacement.length);
  }

  String.prototype.insert=function(index, str) {
      return this.substr(0, index) + str + this.substr(index);
  }

  function getIndicesOf(searchStr, str, caseSensitive) {
    var searchStrLen = searchStr.length;
    if (searchStrLen == 0) {
      return [];
    }
    var startIndex = 0, index, indices = [];
    if (!caseSensitive) {
      str = str.toLowerCase();
      searchStr = searchStr.toLowerCase();
    }
    while ((index = str.indexOf(searchStr, startIndex)) > -1) {
      indices.push(index);
      startIndex = index + searchStrLen;
    }
    return indices;
  }

  function handleFracTag(output) {
    openTag = "\\frac"
    tag_len = openTag.length;

	var indices = getIndicesOf(openTag, output);

	// need to loop backward to avoid the effect of "inserting" to the output
    for (var i = indices.length - 1; i >= 0; --i) {

      var currIndex = indices[i] + tag_len;

      output = output.insert(currIndex, '(');
      currIndex++;

      // loop twice since \frac has "{}" pairs
	  for (var j = 0; j < 2; ++j) {
        if (output[currIndex] == '{') {
          output = output.replaceAt(currIndex, ' ');
		  output = output.insert(currIndex, j == 1 ? '<sub>' : '<sup>');
		  currIndex += 5;

          var leftBrackCount = 1;
          currIndex++;

          while(currIndex < output.length) {
            if (output[currIndex] == '{')
              leftBrackCount++;
            if (output[currIndex] == '}') {
              leftBrackCount--;
              if (leftBrackCount == 0)
                break;
            }
            currIndex++;
          }

          output = output.replaceAt(currIndex, ' ');
		  output = output.insert(currIndex + 1, j == 1 ? '</sub>' : '</sup>');
		  currIndex += 6;
		  
          if (j == 1) { // for the last iteration, no need to insert '/'
            output = output.insert(currIndex + 1, ')');
            break;
          }

          output = output.insert(currIndex + 1, '/');
          currIndex += 2; // to skip '}' and '/';
        }
      }
    }

    return output.replace(/\\frac/g, "");
  }

  function handleSubSupCloseTag(output, openTag, closeTag) {
    tag_len = openTag.length;
    var indices = getIndicesOf(openTag, output);
    for (var i = indices.length - 1; i >= 0; --i) {

      var currIndex = indices[i] + tag_len;

      if (output[currIndex] == '{') {

        var leftBracketCount = 0;

        while(currIndex < output.length) {

          if (output[currIndex] == '{')
            leftBracketCount++;
          if (output[currIndex] == '}') {
            leftBracketCount--;
            if (leftBracketCount == 0)
              break;
          }

          currIndex++;
        }
      }
      output = output.insert(currIndex + 1, closeTag);
    }
    return output;
  }

  function handleUnderlineBlank(output) {
    var indices = getIndicesOf("_", output);
    for (var i = indices.length - 1; i >= 0; --i) {
      if (i % 2 == 1) {
        output = [output.slice(0, indices[i] + 1), " ", output.slice(indices[i] + 1)].join('');
      } else {
        output = [output.slice(0, indices[i]), " ", output.slice(indices[i])].join('');
      }
    }
    return output;
  }

  function match_github_url(str) {
    var matches = str.match(/\bhttps\:\/\/github\.com\/\S+/gi);

    if(matches != null && matches.length > 0)
      return true;
    return false;
  }
  
  function handle_latex_line(input) {
    output = input;
    //output = output.replace(/ /g, "");
    output = output.replace(/_/g, "<sub>");
    output = output.replace(/\^/g, "<sup>");
    output = output.replace(/\$/g, "_");
    output = output.replace(/\\text/g, "");
    output = output.replace(/\\left/g, "");
    output = output.replace(/\\right/g, "");
    output = output.replace(/\\hat\{y\}/g, "ŷ");
  
    output = output.replace(/\\alpha/g, "α");
    output = output.replace(/\\ast/g, " * ");
    output = output.replace(/\\beta/g, "β");
    output = output.replace(/\\delta/g, "δ");
    output = output.replace(/\\Delta/g, "Δ");
    output = output.replace(/\\lambda/g, "λ");
    output = output.replace(/\\mu/g, "μ");
    output = output.replace(/\\partial/g, "∂");
    output = output.replace(/\\pi/g, "π");
    output = output.replace(/\\sigma/g, "σ");
    output = output.replace(/\\Sigma/g, "Σ");
    output = output.replace(/\\sum/g, "Σ");
    output = output.replace(/\\theta/g, "θ");
    output = output.replace(/\\Theta/g, "Θ");
    output = output.replace(/\\varepsilon/g, "ϵ");
  
    output = output.replace(/\\times/g, "×");
    output = output.replace(/\\limits/g, "lim ");
    output = output.replace(/\\cdots/g, " ... ");
    output = output.replace(/\\ldots/g, " ... ");
    output = output.replace(/\\cdot/g, " · ");
    output = output.replace(/\\centerdot/g, " · ");
    output = output.replace(/\\sim/g, " ~ ");
    output = output.replace(/\\ge/g, " ≥ ");
    output = output.replace(/\\le/g, " ≤ ");
    output = output.replace(/\\neq/g, " ≠ ");
    output = output.replace(/\\in/g, " ∈ ");
    output = output.replace(/\\approx/g, " ≈ ");
    output = output.replace(/\\lbrack/g, "[");
    output = output.replace(/\\rbrack/g, "]");
    output = output.replace(/\\langle/g, "〈");
    output = output.replace(/\\rangle/g, "〉");
    output = output.replace(/\\lfloor/g, "⌊");
    output = output.replace(/\\rfloor/g, "⌋");
    output = output.replace(/\\\|/g, "‖");
    output = output.replace(/\\Leftrightarrow/g, "⇔");
    output = handleSubSupCloseTag(output, "<sub>", "</sub>");
    output = handleSubSupCloseTag(output, "<sup>", "</sup>");
    output = handleFracTag(output);
    output = output.replace(/{/g, "");
    output = output.replace(/}/g, "");
    output = output.replace(/\\/g, "");
    output = handleUnderlineBlank(output);
  
    // restore blanks
    output = output.replace(/\=/g, " = ");
    output = output.replace(/\+/g, " + ");
    output = output.replace(/\-/g, " - ");
    
    //remove blanks
    output = output.replace(/\[ /g, "[");
    output = output.replace(/ \]/g, "]");
    output = output.replace(/\( /g, "(");
    output = output.replace(/ \)/g, ")");
    return output;
  }
  
  function handle_img_url(input) {
    output = input;
    output = output.replace("https://github.com", "https://raw.github.com");
    output = output.replace("/raw/master/images", "/master/images");
    output = output.replace("/blob/master/images", "/master/images");
    output = "<p align=\"center\">\n<img src=\"" + output + "\" />\n</p>";
    return output;
  }

  function updateText() {
    input = $("#input").val();
    output = $.trim(input);

    // for python code
    if (output.startsWith("import ")) {
      output = "``` python\n" + output + "\n```\n";
    }
    else {
      var lines = output.split("\n");
      for (var i = 0; i < lines.length; ++i) {
        // for github image url
        if (match_github_url(lines[i])) {
          lines[i] = handle_img_url(lines[i]);
        }
        // for img tag
        else if (lines[i].startsWith("<img ")) {
          lines[i] = "<p align=\"center\">\n" + lines[i] + "\n</p>";
        }
        // for latex content
        else {
          lines[i] = handle_latex_line(lines[i]);
        }
      }
      output = lines.join('\n');
    }

    $("#output").val(output);

    $("#output").select();
    document.execCommand("copy");

    $("#input").focus();
    $("#preview").html(output);
  }

  $("#input").keyup(updateText);
  $("#clear").click(function(){
    $("#input").val("");
    $("#output").val("");
    $("#preview").html("");
  });
  $("#convert").click(updateText);
});
</script>
</head>
<body class="main">
  <div>
    <div>
      <p>
        <ul>
          <li>Convert LaTeX formulas to Markdown format</li>
          <li>Convert Python code to Markdown format</li>
          <li>Convert GitHub image url to referable url</li>
          <li>Wrap up img tag with &lt;p align=&ldquo;&gt;&rdquo;</li>
        </ul>
      </p>
      <textarea id="input" rows="4" cols="50"></textarea>
    </div>

    <div>
      <p>Converted formulas:</p>
      <textarea id="output" rows="3" cols="50"></textarea>
    </div>

    <p>
      <button id="clear">Clear</button>
      <button id="convert">Convert</button>
    </p>

    <div>
      <p id="preview"></p>
    </div>
  </div>
</body>
</html>